﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.Windows.Forms.Design;

namespace PControl
{
    /// <summary>
    /// [Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner)), Designer(typeof(PDesigner))]
    /// 自定义可收缩容器控件，估计用不上
    /// </summary>
    [DesignerAttribute("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
    [Designer(typeof(PDesigner))]
    public partial class CollapsiblePanel : UserControl
    {
        /// <summary>
        /// 标题位置
        /// </summary>
        private TitleDockLocation titleDock = TitleDockLocation.Top;
        /// <summary>
        /// 箭头按钮区域
        /// </summary>
        private Rectangle arrowButtonRectangle = new Rectangle(275, 0, 25, 25);
        private Image arrawBackImage = global::PControl.Properties.Resources.arrow_up;
        /// <summary>
        /// 鼠标是否在箭头按钮上
        /// </summary>
        private bool arrowButtonMouseHover = false;

        private bool isCollapsed;
        private Size preSize;
        private Size currentSize;
        /// <summary>
        /// 用于在控件大小改变时起标识作用，放置因两层调用致使某些属性改变两次
        /// </summary>
        private bool isSizeChangedOk = false;

        public Rectangle ArrowButtonRectangle
        {
            get { return arrowButtonRectangle; }
            set { arrowButtonRectangle = value; }
        }

        public TitleDockLocation TitleDock
        {
            get { return titleDock; }
            set 
            {
                if (titleDock == value)
                {
                    return;
                }
                titleDock = value;
                switch (titleDock)
                {
                    case TitleDockLocation.Top:
                        labTitle.Width = this.Width - 25;
                        labTitle.Height = 25;
                        labTitle.Left = labTitle.Top = 0;
                        btnArrow.Left = this.Width - 25;
                        btnArrow.Top = 0;
                        break;
                    case TitleDockLocation.Left:
                        labTitle.Width = 25;
                        labTitle.Height = this.Height - 25;
                        labTitle.Left = 0;
                        labTitle.Top = 25;
                        btnArrow.Left = btnArrow.Top = 0;
                        break;
                    case TitleDockLocation.Right:
                        labTitle.Width = 25;
                        labTitle.Height = this.Height - 25;
                        labTitle.Left = this.Width - 25;
                        labTitle.Top = 25;
                        btnArrow.Left = this.Width - 25;
                        btnArrow.Top = 0;
                        break;
                    case TitleDockLocation.Bottom:
                        labTitle.Width = this.Width - 25;
                        labTitle.Height = 25;
                        labTitle.Left = 0;
                        labTitle.Top = this.Height - 25;
                        btnArrow.Left = this.Width - 25;
                        btnArrow.Top = this.Height - 25;
                        break;
                }
                this.Invalidate();
            }
        }
        /// <summary>
        /// 箭头按钮鼠标悬停状态
        /// </summary>
        private bool ArrowButtonMouseHover
        {
            get { return arrowButtonMouseHover; }
            set
            {
                if (arrowButtonMouseHover == value)
                {
                    return;
                }
                arrowButtonMouseHover=value;
                if (arrowButtonMouseHover)
                {
                    this.Cursor = Cursors.Hand;
                }
                else
                {
                    this.Cursor = Cursors.Default;
                }
                this.Invalidate(this.arrowButtonRectangle);
            }
        }
        /// <summary>
        /// 控件是否收起
        /// </summary>
        public bool IsCollapsed
        {
            get { return isCollapsed; }
            set
            {
                isCollapsed = value;
            }
        }

        /// <summary>
        /// 设置控件最小尺寸
        /// </summary>
        public new Size MinimunSize
        {
            get { return base.MinimumSize; }
            set
            {
                Size size = value;
                if (titleDock == TitleDockLocation.Top || titleDock == TitleDockLocation.Bottom)
                {
                    if (size.Height < 25)
                    {
                        size.Height = 25;
                    }
                    if (size.Width < 50)
                    {
                        size.Width = 50;
                    }
                }
                else
                {
                    if (size.Height < 50)
                    {
                        size.Height = 50;
                    }
                    if (size.Width < 25)
                    {
                        size.Width = 25;
                    }
                }
                base.MinimumSize = size;
            }
        }
        /// <summary>
        /// 默认构造方法
        /// </summary>
        public CollapsiblePanel()
        {
            InitializeComponent();
            this.palContainer.MouseEnter += new EventHandler(CtrlMouseEnter);
            this.palContainer.ControlAdded += new ControlEventHandler(CtrlAdded);
        }
        /// <summary>
        /// 用于恢复鼠标手势
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CtrlMouseEnter(object sender, EventArgs e)
        {
            if (this.Cursor == Cursors.Hand)
            {
                this.Cursor = Cursors.Default;
                this.Invalidate(this.arrowButtonRectangle);   //局部刷新绘制
            }
        }

        /// <summary>
        /// 子控件也需要绑定恢复鼠标手势方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CtrlAdded(object sender, ControlEventArgs e)
        {
            Control ctrl = e.Control;
            ctrl.MouseEnter += new EventHandler(CtrlMouseEnter);
        }
        /// <summary>
        /// 控件加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CollapsiblePanel_Load(object sender, EventArgs e)
        {
            preSize = this.Size;
        }
        /// <summary>
        /// 控件尺寸改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CollapsiblePanel_SizeChanged(object sender, EventArgs e)
        {
            currentSize = this.Size;
            if (preSize != currentSize)
            {
                if (!isSizeChangedOk)
                {
                    isSizeChangedOk = true;
                    if (currentSize.Height < MinimumSize.Height)
                    {
                        currentSize.Height = MinimumSize.Height;
                    }
                    if (currentSize.Width < MinimumSize.Width)
                    {
                        currentSize.Width = MinimumSize.Width;
                    }
                    this.Size = currentSize;
                }
            }
            if (isSizeChangedOk)
            {
                if (isCollapsed)
                {
                    switch (titleDock)
                    {
                        case TitleDockLocation.Top:
                            labTitle.Width = this.Width - 25;
                            labTitle.Left = labTitle.Top = 0;
                            btnArrow.Left = this.Width - 25;
                            btnArrow.Top = 0;
                            break;
                        case TitleDockLocation.Left:
                            labTitle.Height = this.Height - 25;
                            labTitle.Left = 0;
                            labTitle.Top = 25;
                            btnArrow.Left = btnArrow.Top = 0;
                            break;
                        case TitleDockLocation.Right:
                            labTitle.Height = this.Height - 25;
                            labTitle.Left = this.Width - 25;
                            labTitle.Top = 25;
                            btnArrow.Left = this.Width - 25;
                            btnArrow.Top = 0;
                            break;
                        case TitleDockLocation.Bottom:
                            labTitle.Width = this.Width - 25;
                            labTitle.Left=0;
                            labTitle.Top = this.Height-25;
                            btnArrow.Left = this.Width - 25;
                            btnArrow.Top = this.Height - 25;
                            break;
                    }
                }
                else
                {
                    switch (titleDock)
                    {
                        case TitleDockLocation.Top:
                            labTitle.Width = this.Width - 25;
                            labTitle.Left = labTitle.Top = 0;
                            btnArrow.Left = this.Width - 25;
                            btnArrow.Top = 0;
                            break;
                        case TitleDockLocation.Left:
                            labTitle.Height = this.Height - 25;
                            labTitle.Left = 0;
                            labTitle.Top = 25;
                            btnArrow.Left = btnArrow.Top = 0;
                            break;
                        case TitleDockLocation.Right:
                            labTitle.Height = this.Height - 25;
                            labTitle.Left = this.Width - 25;
                            labTitle.Top = 25;
                            btnArrow.Left = this.Width - 25;
                            btnArrow.Top = 0;
                            break;
                        case TitleDockLocation.Bottom:
                            labTitle.Width = this.Width - 25;
                            labTitle.Left = 0;
                            labTitle.Top = this.Height - 25;
                            btnArrow.Left = this.Width - 25;
                            btnArrow.Top = 0;
                            break;
                    }
                }
                arrowButtonRectangle = new Rectangle(btnArrow.Location, btnArrow.Size);
                this.Invalidate();
                preSize = currentSize;
                isSizeChangedOk = false;
            }
        }

        /// <summary>
        /// 重写-重绘事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            //graphics.
            base.OnPaint(e);
        }
        /// <summary>
        /// 鼠标移动 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.X > this.arrowButtonRectangle.X && e.X < this.arrowButtonRectangle.Width + this.arrowButtonRectangle.X && e.Y > this.arrowButtonRectangle.Y && e.Y < this.arrowButtonRectangle.Y + this.arrowButtonRectangle.Height)
            {
                this.ArrowButtonMouseHover = true;
                btnArrow_MouseHover(btnArrow, e);
            }
            else
            {
                this.ArrowButtonMouseHover = false;
                btnArrow_MouseLeave(btnArrow, e);
            }
            base.OnMouseMove(e);    
        }

        /// <summary>
        /// 将边侧栏收起或展开
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseClick(MouseEventArgs e)
        {
            if (this.arrowButtonMouseHover)
            {
                btnArrow_MouseClick(btnArrow, e);
            }
        }

        /// <summary>
        /// 鼠标离开
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeave(EventArgs e)
        {
            this.arrowButtonMouseHover = false;
            base.OnMouseLeave(e);
        }
        /// <summary>
        /// 重写--鼠标按下事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            /**********如果鼠标不在按钮之上**********/
            if (this.arrowButtonMouseHover)
            {
                btnArrow_MouseDown(btnArrow, e);
            }
            base.OnMouseDown(e);
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            /**********如果鼠标不在按钮之上**********/
            if (this.arrowButtonMouseHover)
            {
                btnArrow_MouseUp(btnArrow, e);
            }
            base.OnMouseUp(e);
        }
        protected override void OnClick(EventArgs e)
        {
            if (this.arrowButtonMouseHover)
            {
                btnArrow_Click(btnArrow, e);
            }
            base.OnClick(e);
        }

        public void btnArrow_MouseHover(object sender, EventArgs e)
        {
            if (isCollapsed)
            {
                switch (titleDock)
                {
                    case TitleDockLocation.Top:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_down_hover;
                        break;
                    case TitleDockLocation.Left:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_right_hover;
                        break;
                    case TitleDockLocation.Right:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_left_hover;
                        break;
                    case TitleDockLocation.Bottom:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_up_hover;
                        break;
                }
            }
            else
            {
                switch (titleDock)
                {
                    case TitleDockLocation.Top:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_up_hover;
                        break;
                    case TitleDockLocation.Left:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_left_hover;
                        break;
                    case TitleDockLocation.Right:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_right_hover;
                        break;
                    case TitleDockLocation.Bottom:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_down_hover;
                        break;
                }
            }
            //this.Invalidate(arrowButtonRectangle);
            //btnArrow.Refresh();
        }

        public void btnArrow_MouseClick(object sender, MouseEventArgs e)
        {
            
        }

        /// <summary>
        /// 鼠标离开箭头按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void btnArrow_MouseLeave(object sender, EventArgs e)
        {
            if (isCollapsed)
            {
                switch (titleDock)
                {
                    case TitleDockLocation.Top:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_down;
                        break;
                    case TitleDockLocation.Left:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_right;
                        break;
                    case TitleDockLocation.Right:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_left;
                        break;
                    case TitleDockLocation.Bottom:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_up;
                        break;
                }
            }
            else
            {
                switch (titleDock)
                {
                    case TitleDockLocation.Top:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_up;
                        break;
                    case TitleDockLocation.Left:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_left;
                        break;
                    case TitleDockLocation.Right:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_right;
                        break;
                    case TitleDockLocation.Bottom:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_down;
                        break;
                }
            }
            //this.Invalidate(arrowButtonRectangle);
            //btnArrow.Refresh();
        }

        /// <summary>
        /// 鼠标按下控件箭头按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void btnArrow_MouseDown(object sender, MouseEventArgs e)
        {
            if (isCollapsed)
            {
                switch (titleDock)
                {
                    case TitleDockLocation.Top:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_down_pressed;
                        break;
                    case TitleDockLocation.Left:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_right_pressed;
                        break;
                    case TitleDockLocation.Right:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_left_pressed;
                        break;
                    case TitleDockLocation.Bottom:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_up_pressed;
                        break;
                }
            }
            else
            {
                switch (titleDock)
                {
                    case TitleDockLocation.Top:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_up_pressed;
                        break;
                    case TitleDockLocation.Left:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_left_pressed;
                        break;
                    case TitleDockLocation.Right:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_right_pressed;
                        break;
                    case TitleDockLocation.Bottom:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_down_pressed;
                        break;
                }
            }
            //this.Invalidate(arrowButtonRectangle);
            //btnArrow.Refresh();
        }

        /// <summary>
        /// 鼠标松开控件箭头按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void btnArrow_MouseUp(object sender, MouseEventArgs e)
        {
            if (isCollapsed)
            {
                switch (titleDock)
                {
                    case TitleDockLocation.Top:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_down_hover;
                        break;
                    case TitleDockLocation.Left:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_right_hover;
                        break;
                    case TitleDockLocation.Right:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_left_hover;
                        break;
                    case TitleDockLocation.Bottom:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_up_hover;
                        break;
                }
            }
            else
            {
                switch (titleDock)
                {
                    case TitleDockLocation.Top:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_up_hover;
                        break;
                    case TitleDockLocation.Left:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_left_hover;
                        break;
                    case TitleDockLocation.Right:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_right_hover;
                        break;
                    case TitleDockLocation.Bottom:
                        arrawBackImage = global::PControl.Properties.Resources.arrow_down_hover;
                        break;
                }
            }
            //btnArrow.Refresh();
            //this.Invalidate(arrowButtonRectangle);
        }

        /// <summary>
        /// 鼠标点击控件箭头按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void btnArrow_Click(object sender, EventArgs e)
        {
            isCollapsed = !isCollapsed;
            //btnArrow.Refresh();
            //this.Invalidate(arrowButtonRectangle);
        }

        private void btnArrow_Paint(object sender, PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            btnArrow.BackgroundImage = arrawBackImage;
        }
    }
    /// <summary>
    /// 控件设计类，添加控件设计时支持
    /// </summary>
    class PDesigner : ControlDesigner
    {
        protected override bool GetHitTest(Point point)
        {
            point = this.Control.PointToClient(point);
            foreach (Control c in this.Control.Controls)
            {
                if (c.Bounds.Contains(point))
                {
                    return true;
                }
            }
            return base.GetHitTest(point);
        }
    }

    /// <summary>
    /// 枚举控件标题栏位置
    /// </summary>
    public enum TitleDockLocation
    {
        Top,Left,Right,Bottom
    }
}
